package org.framework.lazy.cloud.network.heartbeat.protocol.context;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import jakarta.annotation.PreDestroy;
import lombok.extern.slf4j.Slf4j;
import org.framework.lazy.cloud.network.heartbeat.common.context.SocketApplicationListener;
import org.framework.lazy.cloud.network.heartbeat.protocol.filter.NettyHttpProxyFilter;
import org.framework.lazy.cloud.network.heartbeat.protocol.properties.ProtocolProxyProperties;
import org.springframework.stereotype.Component;

@Slf4j
@Component
public class NettyHttpProxySocketApplicationListener implements SocketApplicationListener {

    private final EventLoopGroup bossGroup = new NioEventLoopGroup();
    private final EventLoopGroup workerGroup = new NioEventLoopGroup();
    private final NettyHttpProxyFilter nettyHttpProxyFilter;// 通道业务处理
    private final ProtocolProxyProperties protocolProxyProperties;
    private ChannelFuture channelFuture;

    public NettyHttpProxySocketApplicationListener(NettyHttpProxyFilter nettyHttpProxyFilter, ProtocolProxyProperties protocolProxyProperties) {
        this.nettyHttpProxyFilter = nettyHttpProxyFilter;
        this.protocolProxyProperties = protocolProxyProperties;
    }


    /**
     * 运行
     *
     * @throws InterruptedException
     */
    @Override
    public void doRunning() throws Exception {
        try {
            ProtocolProxyProperties.HttpProtocolProxy httpProtocolProxy = protocolProxyProperties.getHttpProtocolProxy();
            Integer httpProtocolProxyPort = httpProtocolProxy.getPort();
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .handler(new LoggingHandler(LogLevel.INFO))
                    // 给服务端channel设置属性
                    // 设置读缓冲区为2M
                    .childOption(ChannelOption.SO_RCVBUF, 2048 * 1024)
                    // 设置写缓冲区为1M
                    .childOption(ChannelOption.SO_SNDBUF, 1024 * 1024)

                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childOption(ChannelOption.CONNECT_TIMEOUT_MILLIS, 1000 * 60)//连接超时时间设置为 60 秒
                    .childOption(ChannelOption.WRITE_BUFFER_WATER_MARK, new WriteBufferWaterMark(1024 * 1024, 1024 * 1024 * 2))

                    .childHandler(nettyHttpProxyFilter);
            channelFuture = b.bind(httpProtocolProxyPort).sync();

            channelFuture.addListener((ChannelFutureListener) channelFuture -> {
                // 服务器已启动
                log.info("Http 协议代理 服务器启动成功 【{}】", httpProtocolProxyPort);
            });
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            log.error("启动Http 协议代理 失败", e);
        } finally {
            destroy();
            // 服务器已关闭
            log.warn("Http 协议代理 服务关闭");
        }
    }

    @PreDestroy
    @Override
    public void destroy() throws Exception {
        if (channelFuture != null) {
            channelFuture.channel().close().syncUninterruptibly();
        }
        if (!bossGroup.isShutdown()) {
            bossGroup.shutdownGracefully();
        }
        if (!workerGroup.isShutdown()) {
            workerGroup.shutdownGracefully();
        }
    }
}